package middleware

import (
	"context"
	"fmt"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
	"github.com/gogf/gf/v2/os/gctx"
	"github.com/golang-jwt/jwt/v4"
	"shenmawl/internal/dao"
	"shenmawl/internal/model/entity"
	"shenmawl/utility"
	"strings"
)

type UserClaims struct {
	Username string
	jwt.RegisteredClaims
}

// RBAC 权限检查中间件
func RBAC(r *ghttp.Request) {
	ctx := gctx.New() // 创建一个背景上下文
	// 准备要返回的数据
	response := g.Map{
		"code":    403,
		"message": "权限错误",
	}
	token, err := parseToken(r.Cookie.Get("jwt").String())
	if err != nil {
		r.Response.WriteJson(g.Map{
			"code":    202,
			"message": "用户未登录",
		})
	}
	// 从数据库中获取用户的角色和权限
	// 这里假设有一个函数CheckPermission(userID, route)来检查权限
	if !checkPermission(ctx, r, token.Username) {
		r.Response.WriteJson(response)
		//r.Response.WriteStatusExit(403, "Forbidden")
	}

	r.Middleware.Next()
}

// 检查权限的函数
func checkPermission(ctx context.Context, r *ghttp.Request, userName string) bool {
	// 在这里实现从数据库中检查用户权限的逻辑
	// 查询用户的角色
	var SysUser entity.SysUser
	var userRole entity.SysUserRole
	var userRoleMenu []entity.SysRoleMenu
	var userMenu entity.SysMenu
	path := r.URL.Path
	err := dao.SysUser.Ctx(ctx).Where("user_name", userName).Scan(&SysUser)
	if err != nil {
		fmt.Println("查询用户失败:", err)
		return false
	}
	err = dao.SysUserRole.Ctx(ctx).Where("user_id", SysUser.UserId).Scan(&userRole)
	if err != nil {
		fmt.Println("查询用户角色失败:", err)
		return false
	}
	err = dao.SysRoleMenu.Ctx(ctx).Where("role_id", userRole.UserId).Scan(&userRoleMenu)
	// 输出结果
	g.Log().Info(ctx, path)
	//fmt.Println("Users with role_id", userID, ":", gconv.String(userRoleMenu))
	if err != nil {
		fmt.Println("查询用户菜单失败:", err)
		return false
	}
	err = dao.SysMenu.Ctx(ctx).Where("perms", pathHandle(path)).Scan(&userMenu)
	if userMenu.MenuId == 0 {
		return false
	}
	found := false

	// 遍历查找
	for _, rm := range userRoleMenu {
		if rm.MenuId == userMenu.MenuId {
			found = true
			break
		}
	}
	//fmt.Println(userMenu.MenuId)
	if !found {
		return false
	}
	// 返回true表示有权限，false表示无权限
	return true // 示例中默认返回true
}

func pathHandle(path string) string {
	// 要去除的前缀
	prefix := "/api/v1/"

	// 去除前缀
	if strings.HasPrefix(path, prefix) {
		path = strings.TrimPrefix(path, prefix)
	}

	// 将'/'替换为':'
	path = strings.ReplaceAll(path, "/", ":")
	return path
}

func parseToken(tokenString string) (*UserClaims, error) {
	claims := &UserClaims{}

	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		// 保证签发方式是你期望的
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
		}
		return utility.JwtKey, nil
	})

	if err != nil {
		return nil, err
	}

	if claims, ok := token.Claims.(*UserClaims); ok && token.Valid {
		return claims, nil
	}

	return nil, fmt.Errorf("invalid token")
}
